package com.example.blue;

import static com.example.blue.ProcessingFunction.Blank;

import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;

import java.io.File;
import java.io.IOException;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class DataProcessorManager {

    public static int temp = 1;

    // 回调接口，用于向 UI 报告处理结果
    public interface DataUpdateListener {
        void onDataProcessed(ProcessedData data);
    }
    private static DataProcessorManager instance;
    private static final String TAG = "DataProcessorManager";
    private final ConcurrentLinkedQueue<byte[]> dataQueue;
    private final ExecutorService executor;
    private final CombinedDataProcessor processor;
    private ProcessingFunction currentFunction;
    private final Object stateLock = new Object();
    private long lastLogTimeMillis = 0;

    private StringBuffer sb = new StringBuffer();
    private StringBuffer rawsb = new StringBuffer();
    private StringBuffer testsb = new StringBuffer();
    private static String matfile = "modelPara.mat";

    private static String accbiasfile = "AccGyro1.txt";

    private static String magbiasfile = "mag1.txt";

    private static int count = 0;
    private static int startcount = 600;
    private static int testcount = 0;
    private static double[] qs2F = new double[4];
    // UI 线程的 Handler，用于将结果发送到 UI 线程
    private Handler uiHandler = new Handler(Looper.getMainLooper());
    private DataUpdateListener dataUpdateListener;
    private String deviceMac;
    private String handDir="L";

    public void setDeviceMac(String mac){
        deviceMac =mac;
    }
    public void setHandDir(String dir){
        handDir=dir;
    }
    private DataProcessorManager(ConcurrentLinkedQueue<byte[]> dataQueue) {
        this.dataQueue = dataQueue;
        this.executor = Executors.newSingleThreadExecutor();
        this.processor = new CombinedDataProcessor();
        this.currentFunction = Blank; // 默认功能
        qs2F[0] = 0.8243190069059947;
        qs2F[1] = -0.0805442381982586;
        qs2F[2] = -0.0923239194907208;
        qs2F[3] = 0.5527088695112896;
    }
    public static synchronized DataProcessorManager getInstance(ConcurrentLinkedQueue<byte[]> dataQueue) {
        if (instance == null) {
            instance = new DataProcessorManager(dataQueue);
        }
        return instance;
    }
    public void startProcessing() {
        executor.execute(() -> {
            while (!Thread.currentThread().isInterrupted()) {
                byte[] data = dataQueue.poll();
                if (data != null) {
                    ProcessedData result = new ProcessedData("0");
                    synchronized (stateLock) {
                        switch (currentFunction) {
                            //OK
                            case rawdata:
                                result = processor.rawData(data);
                                count++;
                                String rawStr = result.getValue();
                                if (count > 1000 && count < 2000) {
                                    rawsb.append(count + " " + rawStr + "\n");
                                }
                                if (count == 2000) {
                                    try {
                                        count = 0;
                                        currentFunction = Blank;
                                        utils.writeToFile(rawsb.toString(), "rawdata.txt");
                                        rawsb.delete(0, rawsb.length());
                                    } catch (IOException e) {
                                        throw new RuntimeException(e);
                                    }
                                }
                                break;
                            //OK
                            case rawout:
                                result = processor.rawout(data);
                                count++;
                                String rawoutStr = result.getValue();
                                if (count > startcount && count < startcount + 1001) {
                                    sb.append(count + " " + rawoutStr + "\n");
                                    rawsb.append(count + " " + utils.bytesToHex(data) + "\n");
                                }
                                if (count == startcount + 1001) {
                                    try {
                                        count = 0;
                                        currentFunction = Blank;
                                        utils.writeToFile(sb.toString(), "rawout.txt");
                                        utils.writeToFile(rawsb.toString(), "rawdata.txt");
                                        sb.delete(0, sb.length());
                                        rawsb.delete(0, rawsb.length());
                                    } catch (IOException e) {
                                        throw new RuntimeException(e);
                                    }
                                }
                                break;
                            //OK
                            case Blank:
                                count = 0;
                                testcount = 0;
                                sb.delete(0, sb.length());
                                rawsb.delete(0, rawsb.length());
                                result = processor.processFunction3(data);
                                break;

                            case Allout:

                                File magbias = new File(Environment.getExternalStoragePublicDirectory(
                                        Environment.DIRECTORY_DOCUMENTS), magbiasfile);
                                File accgyrobias = new File(Environment.getExternalStoragePublicDirectory(
                                        Environment.DIRECTORY_DOCUMENTS), accbiasfile);

                                ProcessedData res;
                                try {
                                    res = processor.allout(data, accgyrobias.getAbsolutePath(), magbias.getAbsolutePath());
//                                    count = 0;
//                                    sb.delete(0, sb.length());
//                                    rawsb.delete(0, rawsb.length());

                                    count++;
                                    String AlloutStr = res.getValue();
                                    if (count > startcount && count < startcount + 1001) {
                                        sb.append(count + " " + AlloutStr + "\n");
                                        rawsb.append(count + " " + utils.bytesToHex(data) + "\n");
                                    }
                                    if (count == startcount + 1001) {
                                        count = 0;
                                        currentFunction = Blank;
                                        utils.writeToFile(sb.toString(), "allout.txt");
                                        utils.writeToFile(rawsb.toString(), "allout_rawdata.txt");
                                        sb.delete(0, sb.length());
                                        rawsb.delete(0, rawsb.length());
                                    }
                                } catch (IOException e) {
                                    throw new RuntimeException(e);
                                }
                                result = res;
                                break;
                            case MagBias:
                                result = processor.rawout(data);
                                String magoutStr = utils.bytesToHex(data);
                                testcount++;
                                testsb.append(count + " " + result.getValue() + "\n");
                                if(magoutStr.substring(30, 36).equals("000000")
//                                    || magoutStr.substring(30 + 36, 36 + 36).equals("000000")
//                                    || magoutStr.substring(30 + 36*2, 36 + 36*2).equals("000000")
//                                    || magoutStr.substring(30 + 36*3, 36 + 36*3).equals("000000")
//                                    || magoutStr.substring(30 + 36*4, 36 + 36*4).equals("000000")
//                                    || magoutStr.substring(30 + 36*5, 36 + 36*5).equals("000000")
                                    )
                                {
                                    Log.d(TAG, "magoutStr: " + magoutStr.substring(30, 36));
                                    break;

                                }


                                count++;
                                if (count > startcount && count < startcount + 2001) {
                                    sb.append(count + " " + result.getValue() + "\n");
                                    rawsb.append(count + " " + utils.bytesToHex(data) + "\n");
                                }
                                if (count == startcount + 2001) {
                                    try {
                                        count = 0;
                                        testcount = 0;
                                        currentFunction = Blank;
                                        utils.writeToFile(sb.toString(), "magbias_rawout.txt");
                                        utils.writeToFile(rawsb.toString(), "magbias_rawdata.txt");
                                        utils.writeToFile(testsb.toString(), "magbias_test_rawdata.txt");
                                        testsb.delete(0,testsb.length());
                                        sb.delete(0, sb.length());
                                        rawsb.delete(0, rawsb.length());

                                        File magRawoutfile = new File(Environment.getExternalStoragePublicDirectory(
                                                Environment.DIRECTORY_DOCUMENTS), "magbias_rawout.txt");
                                        result = processor.magbias(magRawoutfile.getAbsolutePath());
                                        utils.writeToFile(result.getValue(), "magbias.txt");
                                        magbiasfile = "magbias.txt";
                                    } catch (IOException e) {
                                        throw new RuntimeException(e);
                                    }
                                }
                                break;
                            case Duizhiout:
                                File duizhimagbias = new File(Environment.getExternalStoragePublicDirectory(
                                        Environment.DIRECTORY_DOCUMENTS), magbiasfile);
                                File duizhiaccgyrobias = new File(Environment.getExternalStoragePublicDirectory(
                                        Environment.DIRECTORY_DOCUMENTS), accbiasfile);
                                try {
                                    result = processor.duizhiout(data, duizhiaccgyrobias.getAbsolutePath(), duizhimagbias.getAbsolutePath(), qs2F);
                                    count++;
                                    String duizhioutStr = result.getValue();
                                    if (count > startcount && count < startcount + 1001) {
                                        sb.append(count + " " + duizhioutStr + "\n");
                                        rawsb.append(count + " " + utils.bytesToHex(data) + "\n");
                                    }
                                    if (count == startcount + 1001) {
                                        count = 0;
                                        currentFunction = Blank;
                                        utils.writeToFile(sb.toString(), "duizhiout.txt");
                                        utils.writeToFile(rawsb.toString(), "duizhiout_rawdata.txt");
                                        sb.delete(0, sb.length());
                                        rawsb.delete(0, rawsb.length());

                                        File duizhioutfile = new File(Environment.getExternalStoragePublicDirectory(
                                                Environment.DIRECTORY_DOCUMENTS), "duizhiout.txt");
                                        File modelfile = new File(Environment.getExternalStoragePublicDirectory(
                                                Environment.DIRECTORY_DOCUMENTS), matfile);
                                        result = processor.duizhi(duizhioutfile.getAbsolutePath(), modelfile.getAbsolutePath(), temp);
                                        Log.d(TAG, "Label: "+ result.getFeaResult().predictLabel);
                                        Log.d(TAG, "Score"+ result.getFeaResult().predictScore);
                                    }
                                } catch (IOException e) {
                                    throw new RuntimeException(e);
                                } catch (Exception e) {
                                    throw new RuntimeException(e);
                                }
                                break;
                            case DuizhiBias:
                                count++;
                                File dzmagbias = new File(Environment.getExternalStoragePublicDirectory(
                                        Environment.DIRECTORY_DOCUMENTS), magbiasfile);
                                File dzaccgyrobias = new File(Environment.getExternalStoragePublicDirectory(
                                        Environment.DIRECTORY_DOCUMENTS), accbiasfile);
                                String duizhioutStr = null;
                                try {
                                    duizhioutStr = processor.allout(data, dzaccgyrobias.getAbsolutePath(), dzmagbias.getAbsolutePath()).getValue();
                                } catch (IOException e) {
                                    throw new RuntimeException(e);
                                }
                                if (count > startcount && count < startcount + 101) {
                                    sb.append(count + " " + duizhioutStr + "\n");
                                    rawsb.append(count + " " + utils.bytesToHex(data) + "\n");
                                }
                                if (count == startcount + 101) {
                                    try {
                                        count = 0;
                                        currentFunction = Blank;
                                        utils.writeToFile(sb.toString(), "duizhibias_rawout.txt");
                                        utils.writeToFile(rawsb.toString(), "duizhibias_rawdata.txt");
                                        sb.delete(0, sb.length());
                                        rawsb.delete(0, rawsb.length());

                                        File duizhibiasfile = new File(Environment.getExternalStoragePublicDirectory(
                                                Environment.DIRECTORY_DOCUMENTS), "duizhibias_rawout.txt");
                                        qs2F = processor.duizhibias(duizhibiasfile.getAbsolutePath());
                                        for(double out : qs2F){
                                            Log.d(TAG, "qs2f: " + out);
                                        }
                                        result = new ProcessedData("对指姿势校验完成","duizhibias");
                                    } catch (IOException e) {
                                        throw new RuntimeException(e);
                                    }
                                }
                                break;
                            case AccGyroBias:
                                count++;
                                result = processor.rawout(data);
                                String accoutStr = processor.rawout(data).getValue();
                                if (count > startcount && count < startcount + 1001) {
                                    sb.append(count + " " + accoutStr + "\n");
                                    rawsb.append(count + " " + utils.bytesToHex(data) + "\n");
                                }
                                if (count == startcount + 1001) {
                                    try {
                                        count = 0;
                                        currentFunction = Blank;
                                        utils.writeToFile(sb.toString(), "accgyrobias_rawout.txt");
                                        utils.writeToFile(rawsb.toString(), "accgyrobias_rawdata.txt");
                                        sb.delete(0, sb.length());
                                        rawsb.delete(0, rawsb.length());

                                        File accRawoutfile = new File(Environment.getExternalStoragePublicDirectory(
                                                Environment.DIRECTORY_DOCUMENTS), "accgyrobias_rawout.txt");
                                        result = processor.accgyrobias(accRawoutfile.getAbsolutePath());
                                        utils.writeToFile(result.getValue(), "accgyrobias.txt");
                                        accbiasfile = "accgyrobias.txt";
                                    } catch (IOException e) {
                                        throw new RuntimeException(e);
                                    }
                                }
                                break;
                            case FinalRes:
                                result = processor.zhenchan();
                                currentFunction = Blank;
                                break;
                            case PingJU:
                                count++;

                                File pjmagbias = new File(Environment.getExternalStoragePublicDirectory(
                                        Environment.DIRECTORY_DOCUMENTS), magbiasfile);
                                File pjaccgyrobias = new File(Environment.getExternalStoragePublicDirectory(
                                        Environment.DIRECTORY_DOCUMENTS), accbiasfile);
                                try {
                                    result =  processor.allout(data, pjaccgyrobias.getAbsolutePath(), pjmagbias.getAbsolutePath());
                                    String pjoutStr = processor.allout(data, pjaccgyrobias.getAbsolutePath(), pjmagbias.getAbsolutePath()).getValue();

                                if (count > startcount && count < startcount + 1501) {
                                    sb.append(count + " " + pjoutStr + "\n");
                                    rawsb.append(count + " " + utils.bytesToHex(data) + "\n");
                                }
                                } catch (IOException e) {
                                    throw new RuntimeException(e);
                                }
                                if (count == startcount + 1501) {
                                    try {
                                        count = 0;
                                        currentFunction = Blank;
                                        utils.writeToFile(sb.toString(), "pj_rawout.txt");
                                        utils.writeToFile(rawsb.toString(), "pj_rawdata.txt");
                                        sb.delete(0, sb.length());
                                        rawsb.delete(0, rawsb.length());
                                        result = new ProcessedData("平举文件储存完成","success");
                                    } catch (IOException e) {
                                        throw new RuntimeException(e);
                                    }
                                }
                                break;
                            case JingZhi:
                                count++;
                                File jzmagbias = new File(Environment.getExternalStoragePublicDirectory(
                                        Environment.DIRECTORY_DOCUMENTS), magbiasfile);
                                File jzaccgyrobias = new File(Environment.getExternalStoragePublicDirectory(
                                        Environment.DIRECTORY_DOCUMENTS), accbiasfile);
                                try {
                                    result = processor.allout(data, jzaccgyrobias.getAbsolutePath(), jzmagbias.getAbsolutePath());
                                    String pjoutStr = processor.allout(data, jzaccgyrobias.getAbsolutePath(), jzmagbias.getAbsolutePath()).getValue();
                                    String pjoutaccStr = result.getAcccle();
                                    if (count > startcount && count < startcount + 1501) {
                                        sb.append(count + " " + pjoutStr + "\n");
                                        rawsb.append(count + " " + utils.bytesToHex(data) + "\n");
                                        testsb.append(count + " " + pjoutStr + " "+ pjoutaccStr + "\n");
                                    }
                                } catch (IOException e) {
                                    throw new RuntimeException(e);
                                }
                                if (count == startcount + 1501) {
                                    try {
                                        count = 0;
                                        currentFunction = Blank;
                                        utils.writeToFile(sb.toString(), "jz_rawout.txt");
                                        utils.writeToFile(rawsb.toString(), "jz_rawdata.txt");
                                        utils.writeToFile(testsb.toString(), "jz_acc_outdata.txt");
                                        sb.delete(0, sb.length());
                                        rawsb.delete(0, rawsb.length());
                                        testsb.delete(0, testsb.length());
                                        result = new ProcessedData("文件储存完成","success");
                                    } catch (IOException e) {
                                        throw new RuntimeException(e);
                                    }
                                }
                                break;
                            case WingBeating:
                                count++;
                                File wbmagbias = new File(Environment.getExternalStoragePublicDirectory(
                                        Environment.DIRECTORY_DOCUMENTS), magbiasfile);
                                File wbaccgyrobias = new File(Environment.getExternalStoragePublicDirectory(
                                        Environment.DIRECTORY_DOCUMENTS), accbiasfile);
                                try {
                                    result = processor.allout(data, wbaccgyrobias.getAbsolutePath(), wbmagbias.getAbsolutePath());
                                    String pjoutStr = processor.allout(data, wbaccgyrobias.getAbsolutePath(), wbmagbias.getAbsolutePath()).getValue();

                                    if (count > startcount && count < startcount + 1501) {
                                        sb.append(count + " " + pjoutStr + "\n");
                                        rawsb.append(count + " " + utils.bytesToHex(data) + "\n");
                                    }
                                } catch (IOException e) {
                                    throw new RuntimeException(e);
                                }
                                if (count == startcount + 1501) {
                                    try {
                                        count = 0;
                                        currentFunction = Blank;
                                        utils.writeToFile(sb.toString(), "wb_rawout.txt");
                                        utils.writeToFile(rawsb.toString(), "wb_rawdata.txt");
                                        sb.delete(0, sb.length());
                                        rawsb.delete(0, rawsb.length());
                                        result = new ProcessedData("文件储存完成","success");
                                    } catch (IOException e) {
                                        throw new RuntimeException(e);
                                    }
                                }
                                break;
                            case WingBeatingPlus:
                                count++;
                                File wbpmagbias = new File(Environment.getExternalStoragePublicDirectory(
                                        Environment.DIRECTORY_DOCUMENTS), magbiasfile);
                                File wbpaccgyrobias = new File(Environment.getExternalStoragePublicDirectory(
                                        Environment.DIRECTORY_DOCUMENTS), accbiasfile);
                                try {
                                    result = processor.allout(data, wbpaccgyrobias.getAbsolutePath(), wbpmagbias.getAbsolutePath());
                                    String pjoutStr = processor.allout(data, wbpaccgyrobias.getAbsolutePath(), wbpmagbias.getAbsolutePath()).getValue();

                                    if (count > startcount && count < startcount + 1501) {
                                        sb.append(count + " " + pjoutStr + "\n");
                                        rawsb.append(count + " " + utils.bytesToHex(data) + "\n");
                                    }
                                } catch (IOException e) {
                                    throw new RuntimeException(e);
                                }
                                if (count == startcount + 1501) {
                                    try {
                                        count = 0;
                                        currentFunction = Blank;
                                        utils.writeToFile(sb.toString(), "wbp_rawout.txt");
                                        utils.writeToFile(rawsb.toString(), "wbp_rawdata.txt");
                                        sb.delete(0, sb.length());
                                        rawsb.delete(0, rawsb.length());
                                        result = new ProcessedData("文件储存完成","success");
                                    } catch (IOException e) {
                                        throw new RuntimeException(e);
                                    }
                                }
                                break;
                            default:
                                result = new ProcessedData("0");
                                break;
                        }
                    }
                    final ProcessedData finalResult = result;
                    // 通过 UI Handler 将处理结果发送给监听器
                    if (dataUpdateListener != null) {
                        uiHandler.post(() -> dataUpdateListener.onDataProcessed(finalResult));
                    }

                    // 每隔 10 秒打印一次日志
                    if (System.currentTimeMillis() - lastLogTimeMillis >= 10000) {
                        Log.d(TAG, "Processor output: " + result.getValue());
                        lastLogTimeMillis = System.currentTimeMillis();
                    }
                }
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    return;
                }
            }
        });
    }

    public void stopProcessing() {
        executor.shutdownNow();
    }

    public void setProcessingFunction(ProcessingFunction function) {
        synchronized (stateLock) {
            this.currentFunction = function;
        }
    }

    // 设置回调监听器的方法
    public void setDataUpdateListener(DataUpdateListener listener) {
        this.dataUpdateListener = listener;
    }


}